package cc.magicjson.design.principles.openclose.vote;

import java.util.*;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class Vote {
    private String five;
    private String three;
    private String one;

    public Vote(String five, String three, String one) {
        this.five = five;
        this.three = three;
        this.one = one;
    }

    public String getFive() {
        return five;
    }

    public String getThree() {
        return three;
    }

    public String getOne() {
        return one;
    }

    public static void main(String[] args) {
        List<Vote> list = Arrays.asList(
            new Vote("Ford", "Bob", "Anna"),
            new Vote("Ford", "Bob", "Anna"),
            new Vote("Ford", "Bob", "Harry"),
            new Vote("Bob", "Ford", "Harry")
        );

        List<String> sortedCandidates = VotingUtils.getSortedCandidates(list);
        System.out.println(sortedCandidates);
    }
}

class VotingUtils {

    public static List<String> getSortedCandidates(List<Vote> votes) {
        // 计算每个候选人的总分数
        Map<String, Integer> scoreMap = votes.stream()
            .flatMap(vote -> Stream.of(
                new AbstractMap.SimpleEntry<>(vote.getFive(), 5),
                new AbstractMap.SimpleEntry<>(vote.getThree(), 3),
                new AbstractMap.SimpleEntry<>(vote.getOne(), 1)
            ))
            .collect(Collectors.toMap(
                Map.Entry::getKey,
                Map.Entry::getValue,
                Integer::sum
            ));

        // 对候选人进行排序并提取名字
        return scoreMap.entrySet().stream()
            .sorted((e1, e2) -> {
                int scoreComparison = e2.getValue().compareTo(e1.getValue());
                if (scoreComparison != 0) {
                    return scoreComparison;
                } else {
                    return e1.getKey().compareTo(e2.getKey());
                }
            })
            .map(Map.Entry::getKey)
            .collect(Collectors.toList());
    }
}
